package org.jeecg.modules.payment.util;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fasterxml.jackson.databind.JsonNode;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.request.CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1;
import com.icbc.api.response.CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1;
import com.icbc.api.utils.IcbcSignature;
import com.icbc.api.utils.WebUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.JacksonUtil;
import org.jeecg.modules.payment.bo.IcBcPayChannel;
import org.jeecg.modules.payment.bo.PaymentParams;
import org.jeecg.modules.payment.enums.PayWayEnums;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;


/**
 * @author by Sean
 * @desc: 工商银行聚合支付接口请求工具类
 * @since 2024-05-31 星期五 11:21:42
 */
public class IcbcApiUtil {

    private static final String SIGN_TYPE = IcbcConstants.SIGN_TYPE_RSA2;

    //聚合支付B2C线上消费下单接口
    private static final String CREATE_ORDER_API = "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1";

    //聚合支付B2C线上消费查询
    private static final String QUERY_ORDER_API = "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/orderqry/V1";

    //聚合支付B2C线上退货接口
    private static final String CREATE_REFUND_API = "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/merrefund/V1";

    //聚合支付B2C线上退货查询
    private static final String QUERY_REFUND_API = "https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/refundqry/V1";


    public static JsonNode createOrder(PaymentParams params, IcBcPayChannel payChannel){
        // 设置请求对象request
        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1 request =
                new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1();
        request.setServiceUrl(CREATE_ORDER_API);
        CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1
                .CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz bizContent =
                new CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1
                        .CardbusinessAggregatepayB2cOnlineConsumepurchaseRequestV1Biz();
        request.setBizContent(bizContent);
        //请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
        bizContent.setMer_id(payChannel.getIcbcMesId());
        bizContent.setOut_trade_no(params.getTradeNo());

        String payMode = "";
        PayWayEnums payWay = PayWayEnums.getEnumByValue(params.getPayWay());
        switch (payWay) {
            case WECHAT_PAY:
                payMode = "9";
                break;
            case ALIPAY_PAY:
                payMode = "10";
                break;
            default:
                break;
        }
        bizContent.setPay_mode(payMode);
        //TODO 默认先设置9 后面通过参数判断
        bizContent.setAccess_type("9"); //收单接入方式 5-APP，7-微信公众号，8-支付宝生活号，9-微信小程序
        bizContent.setMer_prtcl_no(payChannel.getMerPrtclNo());
        bizContent.setDecive_info("013467007045764");
        bizContent.setOpen_id(params.getOpenId());
        // 格式化时间为 yyyy-MM-dd'T'HH:mm:ss，去除毫秒部分
        LocalDateTime now = LocalDateTime.now();
        String origDateTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
        //String origDateTime = now.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        bizContent.setOrig_date_time(origDateTime);
        bizContent.setBody(params.getDescription());
        bizContent.setFee_type("001");  //人民币
        bizContent.setSpbill_create_ip("127.0.0.1");  //提交用户端ip
        String totalFee = params.getPayAmount().multiply(BigDecimal.valueOf(100)).toBigInteger().toString();
        bizContent.setTotal_fee(totalFee);  //金额分
        bizContent.setMer_url(params.getPaymentNotifyUrl()); //回调地址
        bizContent.setShop_appid(payChannel.getWxAppId());  //微信开放平台appid
        bizContent.setIcbc_appid(payChannel.getAppId());  //工商api平台appid
        // （商户付给银行手续费的账户，可以在开户的时候指定，也可以用交易指定方式；用交易指定方式则使用此商户账号）
        bizContent.setExpire_time("120"); //订单失效时间，单位为秒，建议大于60秒
        bizContent.setAttach("附加数据"); //附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的 自定义数据
        bizContent.setNotify_type("HS"); //HS-主动推送  AG-不通知用户
        bizContent.setResult_type("1");  // 0-不管失败成都推送 1-支付成功才通知
        CardbusinessAggregatepayB2cOnlineConsumepurchaseResponseV1 response;
        try {
            DefaultIcbcClient client = new DefaultIcbcClient(payChannel.getAppId(), SIGN_TYPE, payChannel.getPrivateKey(),
                payChannel.getApiGwPublicKey());
            response = client.execute(request, IdWorker.get32UUID());//msgId消息通讯唯一编号，要求每次调用独立生成，APP级唯一
            if (response.getReturnCode() == 0) {
                // 6、业务成功处理，请根据接口文档用response.getxxx()获取同步返回的业务数据
                System.out.println("ReturnCode:" + response.getReturnCode());
                System.out.println("response:" + JSON.toJSONString(response));
                JsonNode jsonNodes = JacksonUtil.parseJSONArray(response);
                return jsonNodes;
            } else {
                // 失败
                System.out.println("response:" + JSON.toJSONString(response));
                System.out.println("ReturnCode:"+response.getReturnCode());
                System.out.println("ReturnMsg:"+response.getReturnMsg());
                return null;
            }
        } catch (IcbcApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String notifyStr(boolean checkResult, String msgId, IcBcPayChannel payChannel) {
        // return_code为数字，成功时为0
        String responseBizContent;
        if (checkResult) {
            responseBizContent = "{\"return_code\":0,\"return_msg\":\"success\",\"msg_id\":\"" + msgId + "\"}";
        } else {
            responseBizContent = "{\"return_code\":-1,\"return_msg\":\"icbc sign not pass.\"}";
        }
        // sign_type-商户在工行登记app的签名类型保持一致，一般为RSA2
        // 返回字符串顺序不能变，为response_biz_content、sign_type、sign，中间不含空格换行符；
        String signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":\"RSA2\"";
        String sign = null;
        try {
            sign = IcbcSignature.sign(signStr, IcbcConstants.SIGN_TYPE_RSA2, payChannel.getPrivateKey(),"UTF-8","");
        } catch (IcbcApiException e) {
            throw new JeecgBootException("【工商银行】微信回调-应答签名失败", e);
        }
        return  "{" + signStr + ",\"sign\":\"" + sign + "\"}";
    }



    /**
     * 验证签名
     * @param params
     * @return
     */
    public static Boolean verifySign(Map<String, String> params, IcBcPayChannel payChannel){
        String signStr= WebUtils.buildOrderedSignStr("/rental/pay/wechat/icbcCallBack", params);
        try {
            boolean flag= IcbcSignature.verify(signStr, params.get("sign_type"), payChannel.getPrivateKey(), params.get("charset"), params.get("sign"));
            return flag;
        } catch (IcbcApiException e) {
            throw new JeecgBootException(e);
        }
    }

    public static String generateSignature(String content, String signType, IcBcPayChannel payChannel) throws IcbcApiException {
        return IcbcSignature.sign(content, signType, payChannel.getPrivateKey() , "UTF-8");
    }

}
